package com.ruleKiesession;

import com.pojo.Person;
import com.pojo.School;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.internal.command.CommandFactory;

import java.util.ArrayList;
import java.util.List;

public class RuleKiesession {
    @Test
    public void testkieSessionType() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        /**
         * java.lang.RuntimeException:
         * Trying to create a stateful KieSession from a stateless KieSessionModel: isKiesession
         * 默认是创建有状态的session
         * <ksession name="isKiesession" type="stateless"/>
         * 当配置文件指定为stateless时，会报错
         */
        KieSession ks = kc.newKieSession("isKiesession");
        Person person = new Person();
        person.setName("张三");
        person.setAge(30);
        ks.insert(person);
        int count = ks.fireAllRules();
        System.out.println("总执行了" + count + "条规则");
        ks.dispose();
    }
    @Test
    public void testkieSessionType2() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks = kc.newKieSession("kiesession");
        Person person = new Person();
        person.setName("aaaa");
        person.setAge(11);
        ks.insert(person);
        int count = ks.fireAllRules();
        System.out.println("主线程总执行了" + count + "条规则");
//        testkieSessionType2();
        /**
         * stateful 类型的session在调用的时候，在kisServer中会出现迭代方式插入的问题，造成栈溢出
         */
//        ks.dispose();
    }

    @Test
    public void testStatelessKIESession() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        StatelessKieSession kieSession = kc.newStatelessKieSession("stateless");
        Person person = new Person();
        person.setName("张三");
        person.setAge(30);
        /**
         * execute(Object object) 是将用户数据通过命名的方式进行传输的。
         * 无状态会话调用规则从java代码嗲用execute(Object object)开始
         * 该方法是一次性执行的，它将内部实例化kiesession，并且调用fireAllRules()
         * 然后再finally()中调用dispose()方法，
         * 所以在execute()之后不能在调用会话的其他操作
         *
         * execute() 的执行逻辑
         *
         *      public void execute(Object object) {
         *         //1: 创建一个新的 StatefulKnowledgeSession
         *         StatefulKnowledgeSession ksession = newWorkingMemory();
         *         try {
         *             //2: 执行触发规则的方法
         *             ksession.insert( object );
         *             ksession.fireAllRules();
         *         } finally {
         *             //3: 释放资源
         *             dispose(ksession);
         *         }
         *     }
         *
         *  无状态的session，一次只能执行一个规则，不能重复执行
         *  不会产生笛卡尔积的问题。会适时的创建和清空当前的 KieSession
         *
         */
        kieSession.execute(person);
    }

    @Test
    public void testStatelessKIESession2() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        StatelessKieSession kieSession = kc.newStatelessKieSession("stateless");
        Person person = new Person();
        person.setName("张三");
        School school=new School();
        school.setClassName("一班");
        kieSession.execute(person);
        kieSession.execute(school);
    }
    @Test
    public void testStatelessKIESession3() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        StatelessKieSession kieSession = kc.newStatelessKieSession("stateless");
        Person person = new Person();
        person.setName("张三");
        School school=new School();
        school.setClassName("一班");
        /**
         * 如果想要通过无状态的session 一次性插入多个对象，那么可以通过批量执行命令的方式
         */
        List cmds = new ArrayList();
        cmds.add( CommandFactory.newInsert(person) );
        cmds.add( CommandFactory.newInsert(school) );
        kieSession.execute( CommandFactory.newBatchExecution( cmds ));
    }


    public static void main(String[] args) throws InterruptedException {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks = kc.newKieSession("kiesession2");
        for (int i = 0; i < 5; i++) {
            Person person = new Person();
            person.setAge(i);
//            ks.insert(person);
//            ks.insert(person);
//            int count = ks.fireAllRules();
            MyThread myThread = new MyThread(ks, person);
            Thread tempThread = new Thread(myThread);
            tempThread.start();
            Thread.sleep(100);
        }
        Person person = new Person();
        person.setName("aaaa");
        person.setAge(11);
        ks.insert(person);
        int count = ks.fireAllRules();
        System.out.println("主线程总执行了" + count + "条规则");
        ks.dispose();
    }


}

/**
 * 自定义线程查询 Sql 并启动 自定义线程 MyThreadFile
 */
class MyThread implements Runnable {
    private KieSession kieSession;
    private Person person;

    public MyThread(KieSession kieSession, Person person) {
        this.kieSession = kieSession;
        this.person = person;
    }

    public void run() {
        try {
            person.setName(Thread.currentThread().getName());
            kieSession.insert(person);
            int count = kieSession.fireAllRules();
            System.out.println("子线程总执行了" + count + "条规则");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}